package com.fy.market.generator;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.function.ConverterFileName;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * DDD风格 MyBatis-Plus 代码生成器
 * 只需配置数据库账号、密码、库名，自动生成所有表的代码
 * 生成的文件分包存放，便于复制到DDD各层
 *
 * @author fwq
 */
public class CodeGenerator {
    // ======= 只需修改下面3个配置 =======
    private static final String JDBC_URL = "jdbc:mysql://42.193.219.140:3306/fy_market_001?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowPublicKeyRetrieval=true&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8&autoReconnect=true";
    private static final String JDBC_USERNAME = "fy_market";
    private static final String JDBC_PASSWORD = "fwq4221@";
    // ===================================

    // 包名
    private static final String PACKAGE_NAME = "com.fy.market";

    /**
     * 获取数据库中所有表名
     */
    private static List<String> getAllTables() throws Exception {
        List<String> tables = new ArrayList<>();
        Class.forName("com.mysql.cj.jdbc.Driver");
        try (Connection conn = DriverManager.getConnection(JDBC_URL, JDBC_USERNAME, JDBC_PASSWORD);
             Statement stmt = conn.createStatement()) {
            Pattern pattern = Pattern.compile("jdbc:mysql://[^/]+/([^?]+)");
            Matcher matcher = pattern.matcher(JDBC_URL);
            String dbName = matcher.find() ? matcher.group(1) : "";
            if (dbName.isEmpty()) throw new Exception("无法从URL中解析数据库名");
            ResultSet rs = stmt.executeQuery("SELECT table_name FROM information_schema.tables WHERE table_schema = '" + dbName + "' AND table_type = 'BASE TABLE'");
            while (rs.next()) tables.add(rs.getString(1));
        }
        return tables;
    }

    /**
     * 转换表名为驼峰命名
     */
    private static String convertToCamelCase(String tableName) {
        StringBuilder result = new StringBuilder();
        String[] words = tableName.toLowerCase().split("_");
        for (String word : words) {
            if (word.isEmpty()) continue;
            switch (word) {
                case "id":
                    result.append("ID");
                    break;
                case "url":
                    result.append("URL");
                    break;
                default:
                    result.append(Character.toUpperCase(word.charAt(0))).append(word.substring(1).toLowerCase());
            }
        }
        return result.toString();
    }

    public static void main(String[] args) {
        try {
            List<String> tables = getAllTables();
            if (tables.isEmpty()) {
                System.out.println("数据库中没有找到任何表！");
                return;
            }
            System.out.println("找到以下表：" + String.join(", ", tables));
            String projectPath = System.getProperty("user.dir") + "/codegen-output"; // 生成到 codegen-output 目录

            // 文件名转换器
            ConverterFileName entityNameConverter = CodeGenerator::convertToCamelCase;
            ConverterFileName mapperNameConverter = tableName -> convertToCamelCase(tableName) + "Mapper";
            ConverterFileName serviceNameConverter = tableName -> "I" + convertToCamelCase(tableName) + "Service";
            ConverterFileName serviceImplNameConverter = tableName -> convertToCamelCase(tableName) + "ServiceImpl";
            ConverterFileName controllerNameConverter = tableName -> convertToCamelCase(tableName) + "Controller";

            FastAutoGenerator.create(JDBC_URL, JDBC_USERNAME, JDBC_PASSWORD)
                    .globalConfig(builder -> builder
                            .author("fwq")
                            .dateType(DateType.ONLY_DATE)
                            .commentDate("yyyy-MM-dd")
                            .outputDir(projectPath + "/java")
                            .fileOverride()
                            .disableOpenDir()
                            .enableSwagger() // 开启Swagger注解
                            .enableSpringdoc() // 开启Springdoc注解
                    )
                    .packageConfig(builder -> builder
                            .parent(PACKAGE_NAME)
                            .entity("model.entity")
                            .service("service")
                            .serviceImpl("service.impl")
                            .mapper("mapper")
                            .controller("controller")
                            .pathInfo(Collections.singletonMap(OutputFile.xml, projectPath + "/resources/mapper"))
                    )
                    .strategyConfig(builder -> builder
                            .addInclude(tables)
                            .entityBuilder()
                            .enableLombok()
                            .enableTableFieldAnnotation()
                            .naming(NamingStrategy.no_change)
                            .columnNaming(NamingStrategy.no_change)
                            .enableRemoveIsPrefix()
                            .convertFileName(entityNameConverter)
                            .build()
                            .controllerBuilder()
                            .enableRestStyle()
                            .convertFileName(controllerNameConverter)
                            .enableHyphenStyle()
                            .build()
                            .serviceBuilder()
                            .convertServiceFileName(serviceNameConverter)
                            .convertServiceImplFileName(serviceImplNameConverter)
                            .build()
                            .mapperBuilder()
                            .enableMapperAnnotation()
                            .enableBaseResultMap()
                            .enableBaseColumnList()
                            .convertMapperFileName(mapperNameConverter)
                            .convertXmlFileName(mapperNameConverter)
                            .build()
                    )
                    .templateEngine(new FreemarkerTemplateEngine())
                    .execute();

            System.out.println("代码生成完成！请到 codegen-output 目录下查看。");
        } catch (Exception e) {
            System.out.println("代码生成失败：" + e.getMessage());
            e.printStackTrace();
        }
    }
}